package uk.ac.durham.tel.synergynet.covanto.workspace.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;

import uk.ac.durham.tel.commons.collections.CollectionChangeListener;
import uk.ac.durham.tel.commons.collections.ObservableList;
import uk.ac.durham.tel.synergynet.covanto.project.model.ProjectInfo;

public class WorkspaceRoot {
	private IWorkspaceRoot workspaceRoot;
	private List<ProjectInfo> projectInfoList;
	private ObservableList<List<ProjectInfo>, ProjectInfo> observableProjectInfoList;
	private Map<IProject, ProjectInfo> projectInfoResourceMap = new HashMap<IProject, ProjectInfo>();
	
	private IResourceChangeListener projectResourceChangeListener = new IResourceChangeListener() {
		@Override
		public void resourceChanged(IResourceChangeEvent event) {
			try {
				event.getDelta().accept(new IResourceDeltaVisitor() {
					public boolean visit(IResourceDelta delta) throws CoreException {
						if (delta.getResource() instanceof IProject) {
							if (delta.getKind() == IResourceDelta.ADDED) {
								addProjectInfoToList((IProject) delta.getResource());
							} else if (delta.getKind() == IResourceDelta.REMOVED) {
								removeProjectInfoFromList((IProject) delta.getResource());
							}  
						}
						
						return true;
					}
				});
			} catch (CoreException ex) {
				//
			}
		}
	};
	
	public WorkspaceRoot(IWorkspaceRoot workspaceRoot) {
		this.workspaceRoot = workspaceRoot;
		loadProjectInfoList();
		addResourceChangeListener();
	}
	
	private void addResourceChangeListener() {
		ResourcesPlugin.getWorkspace().addResourceChangeListener(projectResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
	}

	public void addProjectListChangeListener(CollectionChangeListener collectionChangeListener) {
		observableProjectInfoList.addChangeListener(collectionChangeListener);
	}
	
	public void removeProjectListChangeListener(CollectionChangeListener collectionChangeListener) {
		observableProjectInfoList.removeChangeListener(collectionChangeListener);
	}
	
	private void removeProjectInfoFromList(IProject projectResource) {
		ProjectInfo projectInfoTobeRemoved = projectInfoResourceMap.get(projectResource);
		projectInfoTobeRemoved.dispose();
		observableProjectInfoList.remove(projectInfoTobeRemoved);
		projectInfoResourceMap.remove(projectResource);
	}
	
	private void addProjectInfoToList(IProject projectResource) {
		ProjectInfo projectInfo = new ProjectInfo(projectResource); 
		observableProjectInfoList.add(projectInfo);
		projectInfoResourceMap.put(projectResource, projectInfo);
	}
	
	private void loadProjectInfoList() {
		projectInfoList = new ArrayList<ProjectInfo>();
		observableProjectInfoList = new ObservableList<List<ProjectInfo>, ProjectInfo>(projectInfoList);
		IProject[] projectResources = workspaceRoot.getProjects();
		for (IProject projectResource : projectResources) {			
			ProjectInfo projectInfo = new ProjectInfo(projectResource);
			observableProjectInfoList.add(projectInfo);
			projectInfoResourceMap.put(projectResource, projectInfo);
		}
	}
	
	public List<ProjectInfo> getProjectInfoList() {
		return observableProjectInfoList.getReadOnlyList();
	}

	public void dispose() {
		// TODO Auto-generated method stub
		
	}
}
